Portfolio Visualizer
How I built an interactive tool that lets anyone backtest a stock portfolio against real market data — and what I learned ditching matplotlib for Plotly along the way.
Why this project?
The first time I ever played with stocks was in high school, with a cool website I can't remember the name of that let my class simulate trading. I thought it might be cool to create something along those lines, and include plenty of visuals that would help to explain the portfolios performance.
I recently read an article that challenged readers to really consider why they choose certain libraries for their work. I would typically use tkinter for GUI applications for example but I ended up loving PyQT way more after trying it. I figured it was time to challenge my mental notion that I should always just use Matplotlib and the natural next choice to learn was Plotly.
How it works
The app is built on Streamlit, which made deploying it almost as simple as a static html page. Data comes from yfinance, which again made my life a lot easier than expected as the data can be obtained through the library without authentication.
The user selects a set of tickers (or just one), a date range, and their initial investment amount. From there the user can decide how much weight each ticker carries in the portfolio. Once the user has finished their input there are four main visualisations: a cumulative return line chart, a drawdown chart, a correlation heatmap, and a pie chart for portfolio weight.
@st.cache_data(ttl=300) def fetch_stock_data(ticker, num_days): try: end_date = datetime.now() start_date = end_date - timedelta(days=num_days) stock = yf.Ticker(ticker) df = stock.history(start=start_date, end=end_date) if df.empty: st.write(f"No data found for ticker '{ticker}'. Please check the symbol.") return None df = df.reset_index() df = df.rename(columns={'Close': 'Price'}) return df[['Date', 'Price', 'Volume', 'High', 'Low', 'Open']] except Exception as e: st.write(f"Error fetching data: {str(e)}") return None
Challenges
The biggest hurdle was having the sliders automatically update. They would often either not redistribute up to 100%, or behave unexpectedly. The solution was to ignore what Streamlit read from the sliders entirely, because the moment any one slider moved, the values Streamlit had already read from all the others were immediately stale.
Takeaways
- 01 Plotly? A major motivator for me on this project was trying out Plotly. I find it to be a little more finnicky than matplotlib, but the interactive capabilities are worth it.
- 02 Persistent Data I wanted to keep this project on the simple side, so I opted to leave out data persistence. If I were to come back to this project I'd probably add some form of persistent storage so users could come back later to see how their mock portfolio performed instead of starting from scratch each time.
- 03 Financial Data Playing with financial data in a low stakes environment is fun and has helped me better understand financial terminology and why certain metrics matter. For instance I noticed that when a portfolio was heavily weighted in a single sector, its performance was more volatile. While I might have already known that to be true in theory it's nice to confirm it in practice.